package spring.cloud.eurekaclientproduct.controller;


import com.ctc.wstx.sw.EncodingXmlWriter;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import rx.Observable;
import spring.cloud.eurekaclientproduct.collapser.UserHystrixCollapser;
import spring.cloud.eurekaclientproduct.service.UserFacade;
import com.spring.cloud.commonutils.vo.UserInfo;
import com.spring.cloud.commonutils.vo.ResultMessage;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

@RestController
public class CircuitBreakerController {

    @Autowired
    private UserFacade userFacade;

    @GetMapping(value = "/cr/timeout",produces = MediaType.APPLICATION_JSON_VALUE)
    public ResultMessage timeout(){
        return userFacade.timeout();
    }

    @GetMapping("/cr/exp/{msg}")
    public ResultMessage exp(@PathVariable("msg") String msg){
        return userFacade.exp(msg);
    }

    @GetMapping("/cr/timeout2")
    public ResultMessage timeout2(){
        return userFacade.timeout2();
    }

    @GetMapping("/cr/asynctimeout")
    public ResultMessage asyncTimeout() throws ExecutionException, InterruptedException {
        Future<ResultMessage> future = userFacade.asyncTimeout();

        return future.get();

    }

    @PostMapping("/cr/exp")
    public List<ResultMessage> exp2(String[] params){
        return userFacade.exp2(params);
    }

    @PostMapping("/cr/exp2")
    public List<ResultMessage> asyncexp(String[] params){
        Observable<ResultMessage> observable = userFacade.asyncExp(params);
        List<ResultMessage> resList = new ArrayList<>();
        observable.forEach((ResultMessage resultMsg)->{
            resList.add(resultMsg);
        });
        return resList;
    }


    @GetMapping("/user/info/{id}")
    public UserInfo testUserInfo(@PathVariable("id") Long id){
        return userFacade.testUserInfo(id);
    }

    @GetMapping("/user/info/cache/{id}")
    public UserInfo getUserInfo2(@PathVariable("id") Long id){
        HystrixRequestContext context = HystrixRequestContext.initializeContext();
        try{
            userFacade.getUserInfo(id);
            userFacade.getUserInfo(id);
            UserInfo user = new UserInfo(id,"user_name_update","note_update");
            userFacade.updateUserInfo(user);
            return userFacade.getUserInfo(id);
        }finally {
            context.shutdown();
        }
    }


    //合并请求
    @GetMapping("/user/infoes/{ids}")
    public List<UserInfo> findUsers(@PathVariable("ids") Long[]ids){
        try{
            List<UserInfo> userList = new ArrayList<>(ids.length);
            List<Future<UserInfo>> futureList = new ArrayList<>(ids.length);
            for(Long id:ids){
                //这里的不能使用execute 而需要使用queue()
                Future<UserInfo> future = new UserHystrixCollapser(userFacade,id).queue();
                futureList.add(future);
            }

            for(Future<UserInfo> fuser: futureList){
                userList.add(fuser.get());
            }
            return userList;
            //userFacade.findUsers(ids);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    @GetMapping("/user/infoes2/{ids}")
    public List<UserInfo> findUsers2(@PathVariable("ids") Long [] ids){
        List<UserInfo> userList = new ArrayList<>(ids.length);
        List<Future<UserInfo>> futureList = new ArrayList<>(ids.length);
        for(Long id:ids){
            //这里的不能使用execute 而需要使用queue()
            Future<UserInfo> future = userFacade.getUser2(id);
            futureList.add(future);
        }

        for(Future<UserInfo> fuser: futureList){
            try{
                userList.add(fuser.get());
            }catch (Exception ex){
                ex.printStackTrace();
            }

        }
        return userList;

    }
}
